(function(window,document,$){
	function Game2048(opt){
		var score = 0;
		var winNum = 2048;
		var isGameOver = true;
		var prefix=opt.prefix, len=opt.len, size=opt.size, margin=opt.margin;
		var view=new View(prefix,len,size,margin);
		view.init();
		var board = new Board(len);
	board.init();
	console.log(board.arr);
	board.onGenerate = function(e) {
		view.addNum(e.x, e.y, e.num);
		 };
		 function start() {  // 开始游戏 
			score = 0;    // 将保存的分数重置为0 
			view.updateScore(0); // 将页面中的分数重置为0 
			view.cleanNum();   // 清空页面中多余的数字单元格 
			board.init();   // 初始化单元格数组 
			board.generate();  // 生成第1个数字 
			board.generate();  // 生成第2个数字 
			isGameOver = false;  // 将游戏状态设为开始 
		  }
		  $('#' + prefix + '_restart').click(start); // 为“重新开始”按钮添加单击事件 
		  start();// 开始游戏 
	  
		 board.onMove = function(e) {
			if (e.to.num >= winNum) {
				 isGameOver = true;
				 setTimeout(function() { view.win(); }, 300);
				 }
			 if (e.to.num > e.from.num) {
			 score += e.to.num; // 累加分数
			 view.updateScore(score); // 更新页面中显示的分数
			 }
			 view.move(e.from, e.to);
			};
		//  board.generate();
		//  board.generate();
		//  board.onGenerate = function(e) {
		// 	view.addNum(e.x, e.y, e.num); // 替换原来的“console.log(e);”
		// 	 };
			//  board.arr = [
			// 	 [0, 0, 0, 2], [0, 2, 0, 2], [2, 2, 2, 2], [0, 2, 4, 0],
			// 	 ];
			// 	 board.moveLeft();
			// 	 console.log(board.arr);
				//  board.onMove = function(e) {
				// 	 view.move(e.from, e.to);
				// 	 };
					 board.onMoveComplete = function(e) {
						if (!board.canMove()) {
							 isGameOver = true;
							 setTimeout(function() { view.over(score); }, 300);
							 }
					 if (e.moved) {
					 setTimeout(function(){ board.generate(); }, 200);
					 }
					 };
					 $(document).keydown(function(e) {
						if(isGameOver){
							return false;
						}
					   switch (e.which) {
						 case 37: board.moveLeft(); break; // 左移
						 case 38: board.moveUp(); break; // 上移
						 case 39: board.moveRight(); break; // 右移
						 case 40: board.moveDown(); break; // 下移
					 }
				 });		
	}
	window['Game2048']=Game2048;
})(window,document,jQuery);
			function View(prefix,len, size, margin){
				this.prefix=prefix;
				this.len=len;
				this.size=size;
				this.margin=margin;
				this.container=$('#'+prefix+'_container');
				var containerSize=len*size+margin*(len+1);
				this.container.css({width: containerSize , height: containerSize});
				this.nums={};
				this.score=$('#'+prefix+'_score');
			}
			View.prototype={
				getPos:function(n){
					return this.margin+n*(this.size+this.margin);
				},
				init:function(){
					for(var x=0,len=this.len;x<len;++x){
					    for (var y = 0; y < len; ++y) {
                        var $cell = $('<div class="' + this.prefix + '-cell"></div>');
                        $cell.css({
                           width: this.size + 'px', height: this.size + 'px',
                           top: this.getPos(x), left: this.getPos(y)
                        }).appendTo(this.container);
					}
				}
			},
			addNum: function(x, y, num) {
				var $num = $('<div class="' + this.prefix + '-num ' +
							  this.prefix + '-num-' + num + ' ">');
				$num.text(num).css({
				  top: this.getPos(x) + parseInt(this.size / 2), // 用于从中心位置展开
				  left: this.getPos(y) + parseInt(this.size / 2) // 用于从中心位置展开
				}).appendTo(this.container).animate({
				  width: this.size + 'px', height: this.size + 'px',
				  lineHeight: this.size + 'px',
				  top: this.getPos(x), left: this.getPos(y)
				}, 100);
				this.nums[x + '-' + y] = $num;
				},
				move: function (from, to) {
					var fromIndex = from.x + '-' + from.y, toIndex = to.x + '-' + to.y;
					var clean = this.nums[toIndex];
					this.nums[toIndex] = this.nums[fromIndex];
					delete this.nums[fromIndex];
					var prefix = this.prefix + '-num-';
					var pos = { top: this.getPos(to.x), left: this.getPos(to.y) };
					this.nums[toIndex].finish().animate(pos, 200, function () {
					  if (to.num > from.num) { // 判断数字是否合并（合并后to.num大于from.num） 
						clean.remove();
						$(this).text(to.num).removeClass(prefix + from.num).addClass(prefix + to.num);
					  }
					});
				  },
					 updateScore: function(score) {
						 this.score.text(score);
						 },
						 win: function() {
							 $('#' + this.prefix + '_over_info').html('<p>您获胜了</p>');
							 $('#' + this.prefix + '_over').removeClass(this.prefix + '-hide');
							 },
							 over: function(score) {
							 $('#' + this.prefix + '_over_info').html('<p>本次得分</p><p>' + score + '</p>');
							 $('#' + this.prefix + '_over').removeClass(this.prefix + '-hide');
							 },
							 cleanNum: function() {
								 this.nums = {};
							     $('#' + this.prefix + '_over').addClass(this.prefix + '-hide');
								 $('.' + this.prefix + '-num').remove();
								 },
		};
		function Board(len) {
			 this.len = len;
			 this.arr = [];
			 }
			 Board.prototype = {
			 init: function() {
			 for (var arr = [], len = this.len, x = 0; x < len; ++x) {
			 arr[x] = [];
			 for (var y = 0; y < len; ++y) {
			 arr[x][y] = 0;
			 }
			}
			this.arr=arr;
	// 		var board = new Board(len);
	// board.init();
	// console.log(board.arr);
		},
		generate: function() {
			var empty = [];
			for (var x = 0, arr = this.arr, len = arr.length; x < len; ++x) {
				for (var y = 0; y < len; ++y) {
   if (arr[x][y] === 0) {
	empty.push({x: x, y: y});
}
}
}
if (empty.length < 1) {
	return false;
}
var pos = empty[Math.floor((Math.random() * empty.length))];
this.arr[pos.x][pos.y] = Math.random() < 0.5 ? 2 : 4;
this.onGenerate({x: pos.x, y: pos.y, num: this.arr[pos.x][pos.y]});
},
onGenerate: function() {},
moveLeft: function() {
	 var moved = false; // 是否有单元格被移动
	 // 外层循环从上到下遍历“行”，内层循环从左到右遍历“列”
	for (var x = 0, len = this.arr.length; x < len; ++x) {
	 for (var y = 0, arr = this.arr[x]; y < len; ++y) {
	 // 从 y + 1 位置开始，向右查找
	 for (var next = y + 1; next < len; ++next) {
	 // 如果 next 单元格是 0，找下一个不是 0 的单元格
	 if (arr[next] === 0) {
	 continue;
	 }
	 // 如果 y 单元格数字是 0，则将 next 移动到 y 位置，然后将 y 减 1 重新查找
	 if (arr[y] === 0) {
	 arr[y] = arr[next];
	 this.onMove({from: {x: x, y: next, num: arr[next]},
	 to: {x: x, y: y, num: arr[y]}});
	 arr[next] = 0;
	 moved = true;
	 --y;
	 // 如果 y 与 next 单元格数字相等，则将 next 移动并合并给 y
	 } else if (arr[y] === arr[next]) {
	 arr[y] *= 2;
	 this.onMove({from: {x: x, y: next, num: arr[next]},
	 to: {x: x, y: y, num: arr[y]}});
	 arr[next] = 0;
	 moved = true;
	 }
	 break;
	 }
	 }
	 }
	 this.onMoveComplete({moved: moved});
	 },
	 moveRight: function () {
		        var moved = false;
		        for (var x = 0; x < this.len; ++x) {
		          for (var y = this.len - 1; y > 0; --y) { // 从右向左开始检查，准备向右移动
		            for (var prev = y - 1; prev >= 0; --prev) { // 从当前位置向左查找可合并项
		              if (this.arr[x][prev] === 0) {
		                continue;
		              }
		              if (this.arr[x][y] === 0) {
		                this.arr[x][y] = this.arr[x][prev];
		                this.onMove({
		                  from: { x: x, y: prev, num: this.arr[x][prev] },
		                  to: { x: x, y: y, num: this.arr[x][y] }
		                });
		                this.arr[x][prev] = 0;
		                moved = true;
		                --y; // 合并后，检查当前元素左侧的下一个元素
		              } else if (this.arr[x][y] === this.arr[x][prev]) {
		                this.arr[x][y] *= 2;
		                this.onMove({
		                  from: { x: x, y: prev, num: this.arr[x][prev] },
		                  to: { x: x, y: y, num: this.arr[x][y] }
		                });
		                this.arr[x][prev] = 0;
		                moved = true;
		              } else {
		                break; // 无法继续向右合并，跳出循环
		              }
		            }
		          }
		        }
		        this.onMoveComplete({ moved: moved })
		    },
		     moveRight: function () {
		        var moved = false;
		        for (var x = 0; x < this.len; ++x) {
		          for (var y = this.len - 1; y > 0; --y) { // 从右向左开始检查，准备向右移动
		            for (var prev = y - 1; prev >= 0; --prev) { // 从当前位置向左查找可合并项
		              if (this.arr[x][prev] === 0) {
		                continue;
		              }
		              if (this.arr[x][y] === 0) {
		                this.arr[x][y] = this.arr[x][prev];
		                this.onMove({
		                  from: { x: x, y: prev, num: this.arr[x][prev] },
		                  to: { x: x, y: y, num: this.arr[x][y] }
		                });
		                this.arr[x][prev] = 0;
		                moved = true;
		                --y; // 合并后，检查当前元素左侧的下一个元素
		              } else if (this.arr[x][y] === this.arr[x][prev]) {
		                this.arr[x][y] *= 2;
		           this.onMove({
			                  from: { x: x, y: prev, num: this.arr[x][prev] },
			                  to: { x: x, y: y, num: this.arr[x][y] }
			                });
			                this.arr[x][prev] = 0;
			                moved = true;
			              } else {
			                break; // 无法继续向右合并，跳出循环
			              }
			            }
			          }
			        }
			        this.onMoveComplete({ moved: moved })
			    },
	
	 moveUp: function () {
		var moved = false;
		for (var y = this.len - 1; y >= 0; --y) {
		  for (var x = this.len - 2; x >= 0; --x) {
			for (var next = x + 1; next < this.len; ++next) {
			  if (this.arr[next][y] === 0) {
				continue;
			  }
			  if (this.arr[x][y] === 0) {
				this.arr[x][y] = this.arr[next][y];
				this.onMove({
				  from: { x: next, y: y, num: this.arr[next][y] },
				  to: { x: x, y: y, num: this.arr[x][y] }
				});
				this.arr[next][y] = 0;
				moved = true;
				--x;
			  } else if (this.arr[x][y] === this.arr[next][y]) {
				this.arr[x][y] *= 2;
				this.onMove({
				  from: { x: next, y: y, num: this.arr[next][y] },
				  to: { x: x, y: y, num: this.arr[x][y] }
				});
				this.arr[next][y] = 0;
				moved = true;
			  }
			  break;
			}
		  }
		}
		this.onMoveComplete({ moved: moved });
	  },
	  moveDown: function () {
		var moved = false;
		for (var y = 0; y < this.len; ++y) {
		  for (var x = 1, arr = this.arr, len = arr.length; x < len; ++x) {
			for (var prev = x - 1; prev >= 0; --prev) {
			  if (arr[prev][y] === 0) {
				continue;
			  }
			  if (arr[x][y] === 0) {
				arr[x][y] = arr[prev][y];
				this.onMove({
				  from: { x: prev, y: y, num: arr[prev][y] },
				  to: { x: x, y: y, num: arr[x][y] }
				});
				arr[prev][y] = 0;
				moved = true;
				++prev;
			  } else if (arr[x][y] === arr[prev][y]) {
				arr[x][y] *= 2;
				this.onMove({
				  from: { x: prev, y: y, num: arr[prev][y] },
				  to: { x: x, y: y, num: arr[x][y] }
				});
				arr[prev][y] = 0;
				moved = true;
			  }
			  break;
			}
		  }
		}
		this.onMoveComplete({ moved: moved });
	  },
	
	 onMove: function() {},
	 onMoveComplete: function() {},
	 canMove: function() {
		 for (var x = 0, arr = this.arr, len = arr.length; x < len; ++x) {
		 for (var y = 0; y < len; ++y) {
		 if (arr[x][y] === 0) {
		 return true;
		 }
		 var curr = arr[x][y], right = arr[x][y + 1];
		 var down = arr[x + 1] ? arr[x + 1][y] : null;
		 if (right === curr || down === curr) {
		 return true;
		 }
		 }
		 }
		 return false;
		 },
	};